module libeventd.Listener;

import
	libeventd.Types;

enum{
	LEV_OPT_LEAVE_SOCKETS_BLOCKING	= 1u<<0 ,
	LEV_OPT_CLOSE_ON_FREE		= 1u<<1 ,
	LEV_OPT_CLOSE_ON_EXEC		= 1u<<2 ,
	LEV_OPT_REUSEABLE			= 1u<<3 ,
}

extern(C):

alias void function(evconnlistener*, evutil_socket_t, sockaddr*, int socklen, void*) evconnlistener_cb;
alias void function(evconnlistener*, void *) evconnlistener_errorcb;

struct evconnlistener_ops {
	int function(evconnlistener *)	enable;
	int function(evconnlistener *)	disable;
	void function(evconnlistener *)	destroy;
	evutil_socket_t function(evconnlistener *)	getfd;
	event_base*	function(evconnlistener *)	getbase;
}

struct evconnlistener {
	evconnlistener_ops*	ops;
	evconnlistener_cb	cb;
	void*			user_data;
	ev_uint			flags;
}

struct evconnlistener_event {
	evconnlistener	base;
	event		listener;
}

version(Windows){
	struct evconnlistener_iocp {
		evconnlistener 		base;
		evutil_socket_t		fd;
		event_base*		__event_base ;
		event_iocp_port*		port;
		ev_short			n_accepting;
		ev_uint			__shutting_down;
		ev_uint			__event_added;
		accepting_socket**	accepting;
	}
	struct accepting_socket {
		CRITICAL_SECTION	lock;
		event_overlapped	overlapped;
		evutil_socket_t		s;
		deferred_cb		deferred;
		evconnlistener_iocp*	lev;
		ev_uint8_t			buflen;
		ev_uint8_t			family;
		uint				__free_on_cb;	// :1
		char				addrbuf[1];
	}
}


evconnlistener* evconnlistener_new(event_base *base,evconnlistener_cb cb, void *ptr, ev_uint flags, ev_int backlog, evutil_socket_t fd);
evconnlistener* evconnlistener_new_bind(event_base*, evconnlistener_cb, void*, ev_uint , ev_int, sockaddr *sa, ev_int);
void evconnlistener_free(evconnlistener *lev);
ev_int evconnlistener_enable(evconnlistener *lev);
ev_int evconnlistener_disable(evconnlistener *lev);
event_base *evconnlistener_get_base(evconnlistener *lev);
evutil_socket_t evconnlistener_get_fd(evconnlistener *lev);
void evconnlistener_set_error_cb(evconnlistener*, evconnlistener_errorcb);